home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / util / shell / MultiFR12.lha / MultiFR / MultiFR.e < prev   
Text File  |  1995-06-18  |  8KB  |  310 lines

  1. OPT OSVERSION=37
  2. OPT REG=5
  3.  
  4.  
  5. ->/////////////////////////////////////////////////////////////////////////////
  6. ->////////////////////////////////////////////////////// External modules /////
  7. ->/////////////////////////////////////////////////////////////////////////////
  8. MODULE 'dos/dos' , 'dos/exall'
  9.  
  10.  
  11. ->/////////////////////////////////////////////////////////////////////////////
  12. ->//////////////////////////////////////////////////// Exception handling /////
  13. ->/////////////////////////////////////////////////////////////////////////////
  14. RAISE    "ARGS"    IF    ReadArgs()            =    NIL ,
  15.         "MEM"    IF    String()            =    NIL    ,
  16.         "DOS"    IF    Open()                =    NIL    ,
  17.         "DOS"    IF    Read()                =    -1    ,
  18.         "DOS"    IF    Fwrite()            <>    1    ,
  19.         "DOS"    IF    Lock()                =    0    ,
  20.         "DOS"    IF    AllocDosObject()    =    NIL    ,
  21.         "^C"    IF    CtrlC()                =    TRUE
  22.  
  23.  
  24. ->/////////////////////////////////////////////////////////////////////////////
  25. ->////////////////////////////////////////////////// Constant definitions /////
  26. ->/////////////////////////////////////////////////////////////////////////////
  27. ENUM    FIND_STR , REPLACE_STR , FILES , HEX_FIND_STR , HEX_REPLACE_STR , CASE_INSENSITIVE ,
  28.         NUMBER_ARGS
  29.  
  30. ENUM    WRONG_HEX_STRING = "err"
  31.  
  32.  
  33. ->/////////////////////////////////////////////////////////////////////////////
  34. ->/////////////////////////////////////////// Global variable definitions /////
  35. ->/////////////////////////////////////////////////////////////////////////////
  36. DEF    find_str    :    PTR TO CHAR
  37. DEF replace_str    :    PTR TO CHAR
  38.  
  39.  
  40. ->/////////////////////////////////////////////////////////////////////////////
  41. ->//////////////////////////////////////////////////////// Main procedure /////
  42. ->/////////////////////////////////////////////////////////////////////////////
  43. PROC main() HANDLE
  44.  
  45.     DEF rdargs = NIL , args : PTR TO LONG
  46.     DEF files : PTR TO LONG , filename : PTR TO CHAR
  47.     DEF file = NIL , file_start , file_length , file_end
  48.     DEF old_dir_lock = NIL , dir_lock = NIL
  49.  
  50.     PrintF( '          \c1;33;40\cMultiFR\c0;31;40\c v1.2\n' , $9B , $6D , $9B , $6D )
  51.     PutStr( 'Copyright © 1995, Lionel Vintenat\n' )
  52.     PrintF( '\c1;32;40\c---------------------------------\c0;31;40\c\n' , $9B , $6D , $9B , $6D )
  53.  
  54.     rdargs := ReadArgs( 'FS=FIND_STR/A,RS=REPLACE_STR/A,FILES/M/A,' +
  55.                         'HFS=HEX_FIND_STR/S,HRS=HEX_REPLACE_STR/S,CI=CASE_INSENSITIVE/S' ,
  56.                         NEW args[ NUMBER_ARGS ] , NIL )
  57.  
  58.     find_str := get_str( args[ FIND_STR ] , args[ HEX_FIND_STR ] )
  59.     replace_str := get_str( args[ REPLACE_STR ] , args[ HEX_REPLACE_STR ] )
  60.  
  61.     files := args[ FILES ]
  62.  
  63.     WHILE files[]
  64.  
  65.         filename , dir_lock := get_filenames( files[] )
  66.         old_dir_lock := CurrentDir( dir_lock )
  67.  
  68.         WHILE filename
  69.  
  70.             CtrlC()
  71.  
  72.             file :=  Open( filename , OLDFILE )
  73.             file_length := FileLength( filename )
  74.             file_end := ( file_start := NewR( file_length ) ) + file_length
  75.             Read( file , file_start ,  file_length )
  76.             Close( file ) ; file := NIL
  77.  
  78.             file := Open( filename , NEWFILE )
  79.             PutStr( filename )
  80.             parse_file( file , file_start , file_end , args[ CASE_INSENSITIVE ] )
  81.             Close( file ) ; file := NIL
  82.  
  83.             Dispose( file_start )
  84.  
  85.             filename := Next( filename )
  86.  
  87.         ENDWHILE
  88.  
  89.         CurrentDir( old_dir_lock ) ; old_dir_lock := NIL
  90.         UnLock( dir_lock ) ; dir_lock := NIL
  91.  
  92.         files++
  93.  
  94.     ENDWHILE
  95.  
  96. EXCEPT DO
  97.  
  98.     SELECT exception
  99.         CASE "ARGS"
  100.             PrintFault( IoErr() , NIL )
  101.         CASE "MEM"
  102.             PutStr( 'Out of memory !\n' )
  103.         CASE "DOS"
  104.             PrintFault( IoErr() , NIL )
  105.         CASE "^C"
  106.             PutStr( '***user break***\n' )
  107.         CASE WRONG_HEX_STRING
  108.             PutStr( 'Wrong hex string !\n' )
  109.     ENDSELECT
  110.  
  111.     IF old_dir_lock THEN CurrentDir( old_dir_lock )
  112.     IF dir_lock THEN UnLock( dir_lock )
  113.     IF file THEN Close( file )
  114.     IF rdargs THEN FreeArgs( rdargs )
  115.  
  116. ENDPROC
  117.  
  118.  
  119. ->/////////////////////////////////////////////////////////////////////////////
  120. ->//////////////////////////////////////////////////////// Version string /////
  121. ->/////////////////////////////////////////////////////////////////////////////
  122. CHAR '$VER: MultiFR 1.2 (18.6.95)'
  123.  
  124.  
  125. ->/////////////////////////////////////////////////////////////////////////////
  126. ->///////////////////////////////// Returns the given find/replace string /////
  127. ->/////////////////////////////////////////////////////////////////////////////
  128. PROC get_str( rawstr : PTR TO CHAR , hex )
  129.  
  130.     DEF str : PTR TO CHAR
  131.     DEF mod , new_len , i , c
  132.  
  133.     IF hex
  134.  
  135.         mod , new_len := Mod( StrLen( rawstr ) , 2 )
  136.         IF mod THEN Raise( WRONG_HEX_STRING )
  137.         str := String( new_len )
  138.  
  139.         FOR i := 1 TO new_len
  140.  
  141.             SELECT 103 OF ( c := rawstr[]++ )
  142.                 CASE "0" TO "9"
  143.                     str[ i - 1 ] := Shl( c - "0" , 4 )
  144.                 CASE "A" TO "F"
  145.                     str[ i - 1 ] := Shl( c - "A" + 10 , 4 )
  146.                 CASE "a" TO "f"
  147.                     str[ i - 1 ] := Shl( c - "a" + 10 , 4 )
  148.                 DEFAULT
  149.                     Raise( WRONG_HEX_STRING )
  150.             ENDSELECT
  151.  
  152.             SELECT 103 OF ( c := rawstr[]++ )
  153.                 CASE "0" TO "9"
  154.                     str[ i - 1 ] := str[ i - 1 ] + c - "0"
  155.                 CASE "A" TO "F"
  156.                     str[ i - 1 ] := str[ i - 1 ] + c - "A" + 10
  157.                 CASE "a" TO "f"
  158.                     str[ i - 1 ] := str[ i - 1 ] + c - "a" + 10
  159.                 DEFAULT
  160.                     Raise( WRONG_HEX_STRING )
  161.             ENDSELECT
  162.  
  163.         ENDFOR
  164.  
  165.         SetStr( str , new_len )
  166.  
  167.     ELSE
  168.  
  169.         str := String( StrLen( rawstr ) )
  170.         StrCopy( str , rawstr )
  171.  
  172.     ENDIF
  173.  
  174. ENDPROC str
  175.  
  176.  
  177. ->/////////////////////////////////////////////////////////////////////////////
  178. ->//////////////////////////////////////// Parses a file pattern argument /////
  179. ->/////////////////////////////////////////////////////////////////////////////
  180. PROC get_filenames( path_pattern ) HANDLE
  181.  
  182.     DEF pattern , path : PTR TO CHAR , dospattern : PTR TO CHAR
  183.     DEF filenames = NIL , dir_lock
  184.     DEF eac = NIL : PTR TO exallcontrol , ead : PTR TO exalldata
  185.     DEF buffer[ 2048 ] : ARRAY , more , i
  186.  
  187.     pattern := FilePart( path_pattern )
  188.     NEW path[ pattern - path_pattern + 1 ]
  189.     AstrCopy( path , path_pattern , pattern - path_pattern + 1 )
  190.  
  191.     dir_lock := Lock( path , ACCESS_READ )
  192.     eac := AllocDosObject( DOS_EXALLCONTROL , NIL )
  193.     NEW dospattern[ StrLen( pattern ) * 2 + 2 ]
  194.     ParsePatternNoCase( pattern , dospattern , StrLen( pattern ) * 2 + 2 )
  195.     eac.lastkey := NIL
  196.     eac.matchstring := dospattern
  197.     eac.matchfunc := NIL
  198.  
  199.     REPEAT
  200.  
  201.         more := ExAll( dir_lock , buffer , 2048 , ED_NAME , eac )
  202.         ead := buffer
  203.  
  204.         FOR i := 1 TO eac.entries
  205.  
  206.             filenames := Link( String( StrLen( ead.name ) ) , filenames )
  207.             StrCopy( filenames , ead.name )
  208.  
  209.             ead := ead.next
  210.  
  211.         ENDFOR
  212.  
  213.     UNTIL more = FALSE
  214.  
  215.     IF IoErr() <> ERROR_NO_MORE_ENTRIES THEN Raise( "DOS" )
  216.  
  217. EXCEPT DO
  218.  
  219.     IF eac THEN FreeDosObject( DOS_EXALLCONTROL , eac )
  220.     ReThrow()
  221.  
  222. ENDPROC filenames , dir_lock
  223.  
  224.  
  225. ->/////////////////////////////////////////////////////////////////////////////
  226. ->//////////////////////////////////////// Applies Find/Replace to a file /////
  227. ->/////////////////////////////////////////////////////////////////////////////
  228. PROC parse_file( file , file_start , file_end , ci )
  229.  
  230.     DEF file_ptr1 : PTR TO CHAR , file_ptr2 : PTR TO CHAR
  231.  
  232.     file_ptr1 := ( file_ptr2 := file_start )
  233.  
  234.     WHILE file_ptr2 < file_end
  235.  
  236.         IF (     IF ci
  237.                 THEN str_cmp_no_case( find_str , file_ptr2 , EstrLen( find_str ) )
  238.                 ELSE StrCmp( find_str , file_ptr2 , EstrLen( find_str ) )
  239.            )
  240.  
  241.             Fwrite( file , file_ptr1 , file_ptr2 - file_ptr1 , 1 )
  242.             Fwrite( file , replace_str , EstrLen( replace_str ) , 1 )
  243.             file_ptr2 := file_ptr2 + EstrLen( find_str )
  244.             file_ptr1 := file_ptr2
  245.  
  246.             PutStr( '.' )
  247.  
  248.         ELSE
  249.  
  250.             INC file_ptr2
  251.  
  252.         ENDIF
  253.  
  254.     ENDWHILE
  255.  
  256.     PutStr( '\n' )
  257.  
  258.     Fwrite( file , file_ptr1 , file_ptr2 - file_ptr1 , 1 )
  259.  
  260. ENDPROC
  261.  
  262.  
  263. ->/////////////////////////////////////////////////////////////////////////////
  264. ->//////////////////////////////////// Like StrCmp() but case insensitive /////
  265. ->/////////////////////////////////////////////////////////////////////////////
  266. PROC str_cmp_no_case( str1 : PTR TO CHAR , str2 : PTR TO CHAR , len )
  267.  
  268.     DEF i = 0
  269.  
  270.     MOVE.L    str1 , A1
  271.     MOVE.L    str2 , A2
  272.     MOVE.L    len  , D0
  273. loop_while:
  274.     CMP.L    D0 , i
  275.     BEQ.B    end_true
  276.     INC        i
  277.     MOVE.B    (A1)+ , D1
  278.     MOVE.B    (A2)+ , D2
  279.     TST.B    D1
  280.     BNE.B    test2
  281.     TST.B    D2
  282.     BEQ.B    end_true
  283.     RETURN FALSE
  284. test2:
  285.     TST.B    D2
  286.     BEQ.B    end_false
  287. insidewhile:
  288.         CMP.B    D1 , D2
  289.         BEQ.B    loop_while
  290.         CMP.B    #"a" , D1
  291.         BCS.B    char1_ok
  292.         CMP.B    #"z" , D1
  293.         BHI.B    char1_ok
  294.         SUB.B    #32 , D1
  295. char1_ok:
  296.         CMP.B    #"a" , D2
  297.         BCS.B    char2_ok
  298.         CMP.B    #"z" , D2
  299.         BHI.B    char2_ok
  300.         SUB.B    #32 , D2
  301. char2_ok:
  302.         CMP.B    D1 , D2
  303.         BEQ.B    loop_while
  304. end_false:
  305.     RETURN FALSE
  306. end_true:
  307.     RETURN TRUE
  308.  
  309. ENDPROC
  310.